package cn.lanqiao.common.utils;


import com.arcsoft.face.*;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.enums.ErrorInfo;
import com.arcsoft.face.toolkit.ImageInfo;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;

/**
 * @author Marisa
 * @description 虹软人脸识别工具类
 * @date 2022/3/31
 */
public class FaceUtil {
    // 文件地址（指向comm包下的lib包中的WIN64文件夹在你电脑上的绝对路径）
    private static final String libPath= "E:/java/ArcSoft/libs/WIN64";
    // APP key
    private static final String appId  = "GU92SXYopvGZ9Sxdh5BwBq7u3UktM8fmhssrcrb3BswE";
    // SKD key
    private static final String sdkKey = "8GmMZUFPbXBPrmdb6aMne6KTKkggMCxS2oHbndkzsyxg";

    private static final FaceEngine faceEngine;  // 面部引擎
    private static final EngineConfiguration engineConfiguration;        // 引擎配置对象
    private static final FunctionConfiguration functionConfiguration;    // 功能配置对象

    // 初始化引擎基本参数
    static {
            FaceEngine _faceEngine = new FaceEngine(libPath);
            //激活引擎
            int errCode = _faceEngine.activeOnline(appId, sdkKey);
            if (errCode != ErrorInfo.MOK.getValue() && errCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
                System.out.println("引擎激活失败");
            }
            faceEngine = _faceEngine;

            //引擎配置
            EngineConfiguration _engineConfiguration = new EngineConfiguration();
            _engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
            _engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
            _engineConfiguration.setDetectFaceMaxNum(10);
            _engineConfiguration.setDetectFaceScaleVal(16);
            engineConfiguration =_engineConfiguration;

            // 功能配置
            FunctionConfiguration _functionConfiguration = new FunctionConfiguration();
            _functionConfiguration.setSupportAge(true);
            _functionConfiguration.setSupportFace3dAngle(true);
            _functionConfiguration.setSupportFaceDetect(true);
            _functionConfiguration.setSupportFaceRecognition(true);
            _functionConfiguration.setSupportGender(true);
            _functionConfiguration.setSupportLiveness(true);
            _functionConfiguration.setSupportIRLiveness(true);
            functionConfiguration = _functionConfiguration;

    }

    /**
     * 私有化构造函数
     */
    private FaceUtil(){
        super();
    }

    /**
     * 初始化引擎
     */
    public static void init(){
        ActiveFileInfo activeFileInfo = new ActiveFileInfo();
        faceEngine.getActiveFileInfo(activeFileInfo);
        engineConfiguration.setFunctionConfiguration(functionConfiguration);
        //初始化引擎
        faceEngine.init(engineConfiguration);

        }

    /**
     * 人脸检测
     * @param imgPath   文件对象
     * @return          检测结果
     */
    public static Boolean faceDetection(String imgPath){
        // 人脸检测
        ImageInfo imageInfo = getRGBData(new File(imgPath));
        List<FaceInfo> faceInfoList = new ArrayList<>();
        faceEngine.detectFaces(
                imageInfo.getImageData(),
                imageInfo.getWidth(),
                imageInfo.getHeight(),
                imageInfo.getImageFormat(),
                faceInfoList
        );
        return !faceInfoList.isEmpty();
    }

    /**
     * 人脸检测
     * @param base64Str Base64字符串
     * @param fileType  文件类型
     * @return          检测结果
     */
    public static Boolean faceDetection(String base64Str, String fileType){
        File file = null;
        try {
            byte[] bytes = Base64Util.decode(base64Str);
            file = FileUtil.bytesToFile(bytes, fileType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 人脸检测
        if(file!= null){
            ImageInfo imageInfo = getRGBData(file);
            List<FaceInfo> faceInfoList = new ArrayList<>();
            faceEngine.detectFaces(
                    imageInfo.getImageData(),
                    imageInfo.getWidth(),
                    imageInfo.getHeight(),
                    imageInfo.getImageFormat(),
                    faceInfoList
            );
            return !faceInfoList.isEmpty();
        }
        return false;
    }

    /**
     * 获取面部特征
     * @param imgPath   图片地址
     * @return          特征数组
     */
    public static byte[] getFaceFeatures(String imgPath){
        FaceFeature faceFeature = new FaceFeature();
        ImageInfo imageInfo = getRGBData(new File(imgPath));
        List<FaceInfo> faceInfoList = new ArrayList<>();
        return getFeaturesBytes(faceFeature, imageInfo, faceInfoList);
    }

    /**
     * 获取面部特征
     * @param base64Str 图片地址
     * @param fileType  文件类型
     * @return          特征数组
     */
    public static byte[] getFaceFeatures(String base64Str, String fileType){
        File file = null;
        try {
            byte[] bytes = Base64Util.decode(base64Str);
            file = FileUtil.bytesToFile(bytes, fileType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        FaceFeature faceFeature = new FaceFeature();
        ImageInfo imageInfo = getRGBData(file);
        List<FaceInfo> faceInfoList = new ArrayList<>();
        if(file != null){
            return getFeaturesBytes(faceFeature, imageInfo, faceInfoList);
        }
        return new byte[0];
    }

    /**
     * 获取图像的特征
     * @param faceFeature   特征
     * @param imageInfo     图像
     * @param faceInfoList  列表
     * @return              结果
     */
    private static byte[] getFeaturesBytes(FaceFeature faceFeature, ImageInfo imageInfo, List<FaceInfo> faceInfoList) {
        faceEngine.detectFaces(
                imageInfo.getImageData(),
                imageInfo.getWidth(),
                imageInfo.getHeight(),
                imageInfo.getImageFormat(),
                faceInfoList
        );
        if(faceInfoList.isEmpty()){
            return new byte[0];
        }
        faceEngine.extractFaceFeature(
                imageInfo.getImageData(),
                imageInfo.getWidth(),
                imageInfo.getHeight(),
                imageInfo.getImageFormat(),
                faceInfoList.get(0),
                faceFeature
        );
        return faceFeature.getFeatureData();
    }

    /**
     * 人脸特征对比
     * @param imgPath1 图像1路径
     * @param imgPath2 图像2路径
     * @return         对比结果
     */
    public static FaceSimilar faceFeatureComparison(String imgPath1, String imgPath2){
        //特征比对
        FaceFeature targetFaceFeature = new FaceFeature();
        targetFaceFeature.setFeatureData(getFaceFeatures(imgPath1));
        FaceFeature sourceFaceFeature = new FaceFeature();
        sourceFaceFeature.setFeatureData(getFaceFeatures(imgPath2));
        FaceSimilar faceSimilar = new FaceSimilar();

        faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
        return faceSimilar;
    }

    /**
     * 人脸特征对比
     * @param imgPath1  图像1的Base64字符串
     * @param file1Type 图像1类型
     * @param imgPath2  图像2的Base64字符串
     * @param file2Type 图像2类型
     * @return          对比结果
     */
    public static FaceSimilar faceFeatureComparison(String imgPath1, String file1Type, String imgPath2, String file2Type){
        //特征比对
        FaceFeature targetFaceFeature = new FaceFeature();
        targetFaceFeature.setFeatureData(getFaceFeatures(imgPath1, file1Type));

        FaceFeature sourceFaceFeature = new FaceFeature();
        sourceFaceFeature.setFeatureData(getFaceFeatures(imgPath2, file2Type));
        FaceSimilar faceSimilar = new FaceSimilar();

        faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
        return faceSimilar;
    }

    /**
     * 人脸特征对比
     * @param imgPath1  图像1路径
     * @param file1Type 图像1类型
     * @param bytes     图像2特征码
     * @return          对比结果
     */
    public static FaceSimilar faceFeatureComparison(String imgPath1, String file1Type, byte[] bytes){
        //特征比对
        FaceFeature targetFaceFeature = new FaceFeature();
        targetFaceFeature.setFeatureData(getFaceFeatures(imgPath1, file1Type));

        FaceFeature sourceFaceFeature = new FaceFeature();
        sourceFaceFeature.setFeatureData(bytes);
        FaceSimilar faceSimilar = new FaceSimilar();

        faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
        return faceSimilar;
    }

    /**
     * 关闭引擎
     */
    public static void closeEngine(){
        faceEngine.unInit();
    }

    /**
     * 测试用Main方法
     * @param args  args
     */
    public static void main(String[] args) {
        FaceUtil.init();
        String path = "D:\\img\\g.jpg";
        String fileType = "jpg";

        // 人脸检测
        Boolean isFace = FaceUtil.faceDetection(path);
        System.out.println(isFace);

        // 获取面部特征
        byte[] faceFeatures = FaceUtil.getFaceFeatures(path);
        System.out.println(Arrays.toString(faceFeatures));

        // 人脸特征对比
        FaceSimilar faceSimilar = FaceUtil.faceFeatureComparison("D:\\img\\me.jpg", "D:\\img\\me3.jpg");
        System.out.println(faceSimilar.getScore());

        // >>>>>>>>>>>>>>>>Base64图像>>>>>>>>>>>>>>>>
        // 人脸检测
        String s = Base64Util.convertFileToBase64(path);
        Boolean isFace2 = FaceUtil.faceDetection(s, fileType);
        System.out.println(isFace2);

        // 获取面部特征
        byte[] faceFeatures2 = FaceUtil.getFaceFeatures(s, fileType);
        System.out.println(Arrays.toString(faceFeatures2));

        // 人脸特征对比
        String path2 = "D:\\img\\g2.jpg";
        String s2 = Base64Util.convertFileToBase64(path2);
        FaceSimilar faceSimilar2 = FaceUtil.faceFeatureComparison(s, fileType, s2, fileType);
        System.out.println(faceSimilar2.getScore());

        // 人脸特征对比(Base64 比较 特征码)
        FaceSimilar faceSimilar3 = FaceUtil.faceFeatureComparison(s2, fileType, faceFeatures2);
        System.out.println(faceSimilar3.getScore());

        // 关闭引擎
        FaceUtil.closeEngine();
    }
}
